#include "task_config_provider.h"
#include <QFile>
#include <QDir>
#include <QCoreApplication>
#include <QJsonDocument>
#include <QJsonArray>
#include <QDesktopServices>
#include <QUrl>

namespace infrastructure {
namespace configuration {

TaskConfigProvider::TaskConfigProvider(
    const QString& configFilePath,
    std::shared_ptr<kernel::ILogger> logger)
    : m_configFilePath(configFilePath)
    , m_logger(logger)
{
}

// ==================== 读取功能 ====================

kernel::Result<kernel::task::TaskSystemConfigDTO> TaskConfigProvider::loadConfig()
{
    // 参考 task_manager.cpp:218-257

    // 1. 构建完整路径
    QString fullPath = getConfigFilePath();

    // 2. 检查文件是否存在
    if (!QFile::exists(fullPath)) {
        QString error = "Task config file not found: " + fullPath;
        if (m_logger) {
            m_logger->error(error);
        }
        return kernel::Result<kernel::task::TaskSystemConfigDTO>::failure(
            kernel::ErrorCode::NotFound,
            error
        );
    }

    // 3. 打开文件
    QFile file(fullPath);
    if (!file.open(QIODevice::ReadOnly)) {
        QString error = "Could not open task config file: " + fullPath;
        if (m_logger) {
            m_logger->error(error);
        }
        return kernel::Result<kernel::task::TaskSystemConfigDTO>::failure(
            kernel::ErrorCode::IOError,
            error
        );
    }

    // 4. 读取文件内容
    QByteArray data = file.readAll();
    file.close();

    // 5. 解析JSON
    QJsonParseError jsonError;
    QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonError);

    if (jsonError.error != QJsonParseError::NoError) {
        QString error = "JSON parse error: " + jsonError.errorString();
        if (m_logger) {
            m_logger->error(error);
        }
        return kernel::Result<kernel::task::TaskSystemConfigDTO>::failure(
            kernel::ErrorCode::ParseError,
            error
        );
    }

    if (!jsonDoc.isObject()) {
        QString error = "Invalid JSON: root must be an object";
        if (m_logger) {
            m_logger->error(error);
        }
        return kernel::Result<kernel::task::TaskSystemConfigDTO>::failure(
            kernel::ErrorCode::ParseError,
            error
        );
    }

    // 6. 解析配置
    QJsonObject rootObj = jsonDoc.object();
    auto result = parseConfig(rootObj);

    if (result.isSuccess()) {
        m_cachedConfig = result.getValue();
        m_isLoaded = true;

        if (m_logger) {
            m_logger->info(QString("Task config loaded: %1 templates from %2")
                .arg(m_cachedConfig.templates.size())
                .arg(fullPath));
        }
    }

    return result;
}

kernel::Result<kernel::task::TaskSystemConfigDTO> TaskConfigProvider::reloadConfig()
{
    m_isLoaded = false;
    m_cachedConfig = kernel::task::TaskSystemConfigDTO{};
    return loadConfig();
}

kernel::Result<kernel::task::TaskTemplateConfigDTO> TaskConfigProvider::getTemplate(
    const std::string& name)
{
    // 确保已加载
    if (!m_isLoaded) {
        auto loadResult = loadConfig();
        if (!loadResult.isSuccess()) {
            return kernel::Result<kernel::task::TaskTemplateConfigDTO>::failure(
                loadResult.getErrorCode(),
                loadResult.getErrorMessage()
            );
        }
    }

    // 查找模板
    const auto* tmpl = m_cachedConfig.findTemplate(name);
    if (!tmpl) {
        return kernel::Result<kernel::task::TaskTemplateConfigDTO>::failure(
            kernel::ErrorCode::NotFound,
            QString::fromStdString("Template not found: " + name)
        );
    }

    return kernel::Result<kernel::task::TaskTemplateConfigDTO>::success(*tmpl);
}

std::vector<std::string> TaskConfigProvider::getTemplateNames() const
{
    std::vector<std::string> names;
    for (const auto& tmpl : m_cachedConfig.templates) {
        names.push_back(tmpl.name);
    }
    return names;
}

const kernel::task::TaskSystemConfigDTO* TaskConfigProvider::getCachedConfig() const
{
    return m_isLoaded ? &m_cachedConfig : nullptr;
}

// ==================== 写入功能 ====================

kernel::Result<void> TaskConfigProvider::saveConfig(
    const kernel::task::TaskSystemConfigDTO& config)
{
    // 1. 验证配置
    std::string error = config.validate();
    if (!error.empty()) {
        return kernel::Result<void>::failure(
            kernel::ErrorCode::ValidationError,
            QString::fromStdString(error)
        );
    }

    // 2. 转换为JSON
    QJsonObject rootObj = configToJson(config);
    QJsonDocument jsonDoc(rootObj);

    // 3. 写入文件
    QString fullPath = getConfigFilePath();
    QFile file(fullPath);
    if (!file.open(QIODevice::WriteOnly)) {
        QString err = "Could not open file for writing: " + fullPath;
        if (m_logger) {
            m_logger->error(err);
        }
        return kernel::Result<void>::failure(
            kernel::ErrorCode::IOError,
            err
        );
    }

    file.write(jsonDoc.toJson(QJsonDocument::Indented));
    file.close();

    // 4. 更新缓存
    m_cachedConfig = config;
    m_isLoaded = true;

    if (m_logger) {
        m_logger->info(QString("Task config saved to %1").arg(fullPath));
    }

    return kernel::Result<void>::success();
}

kernel::Result<void> TaskConfigProvider::addTemplate(
    const kernel::task::TaskTemplateConfigDTO& tmpl)
{
    // 确保已加载
    if (!m_isLoaded) {
        auto loadResult = loadConfig();
        if (!loadResult.isSuccess()) {
            return kernel::Result<void>::failure(
                loadResult.getErrorCode(),
                loadResult.getErrorMessage()
            );
        }
    }

    // 检查是否已存在
    if (m_cachedConfig.findTemplate(tmpl.name) != nullptr) {
        return kernel::Result<void>::failure(
            kernel::ErrorCode::AlreadyExists,
            QString::fromStdString("Template already exists: " + tmpl.name)
        );
    }

    // 添加并保存
    m_cachedConfig.templates.push_back(tmpl);
    return saveConfig(m_cachedConfig);
}

kernel::Result<void> TaskConfigProvider::updateTemplate(
    const std::string& name,
    const kernel::task::TaskTemplateConfigDTO& tmpl)
{
    // 确保已加载
    if (!m_isLoaded) {
        auto loadResult = loadConfig();
        if (!loadResult.isSuccess()) {
            return kernel::Result<void>::failure(
                loadResult.getErrorCode(),
                loadResult.getErrorMessage()
            );
        }
    }

    // 查找并更新
    bool found = false;
    for (auto& t : m_cachedConfig.templates) {
        if (t.name == name) {
            t = tmpl;
            found = true;
            break;
        }
    }

    if (!found) {
        return kernel::Result<void>::failure(
            kernel::ErrorCode::NotFound,
            QString::fromStdString("Template not found: " + name)
        );
    }

    return saveConfig(m_cachedConfig);
}

kernel::Result<void> TaskConfigProvider::removeTemplate(const std::string& name)
{
    // 确保已加载
    if (!m_isLoaded) {
        auto loadResult = loadConfig();
        if (!loadResult.isSuccess()) {
            return kernel::Result<void>::failure(
                loadResult.getErrorCode(),
                loadResult.getErrorMessage()
            );
        }
    }

    // 查找并删除
    auto it = std::remove_if(
        m_cachedConfig.templates.begin(),
        m_cachedConfig.templates.end(),
        [&name](const kernel::task::TaskTemplateConfigDTO& t) {
            return t.name == name;
        }
    );

    if (it == m_cachedConfig.templates.end()) {
        return kernel::Result<void>::failure(
            kernel::ErrorCode::NotFound,
            QString::fromStdString("Template not found: " + name)
        );
    }

    m_cachedConfig.templates.erase(it, m_cachedConfig.templates.end());
    return saveConfig(m_cachedConfig);
}

// ==================== 工具方法 ====================

QString TaskConfigProvider::getConfigFilePath() const
{
    // 如果是绝对路径，直接返回
    QFileInfo fileInfo(m_configFilePath);
    if (fileInfo.isAbsolute()) {
        return m_configFilePath;
    }

    // 相对路径：相对于应用程序目录
    QString appDir = QCoreApplication::applicationDirPath();
    return QDir(appDir).filePath(m_configFilePath);
}

bool TaskConfigProvider::openConfigDirectory() const
{
    QString fullPath = getConfigFilePath();
    QFileInfo fileInfo(fullPath);
    QString dirPath = fileInfo.absolutePath();

    return QDesktopServices::openUrl(QUrl::fromLocalFile(dirPath));
}

// ==================== JSON解析 ====================

kernel::Result<kernel::task::TaskSystemConfigDTO> TaskConfigProvider::parseConfig(
    const QJsonObject& rootObj)
{
    // 参考 task_manager.cpp:258-312

    kernel::task::TaskSystemConfigDTO config;

    // 解析 tasks 数组
    if (!rootObj.contains("tasks") || !rootObj["tasks"].isArray()) {
        return kernel::Result<kernel::task::TaskSystemConfigDTO>::failure(
            kernel::ErrorCode::ParseError,
            "Missing or invalid 'tasks' array"
        );
    }

    QJsonArray tasksArray = rootObj["tasks"].toArray();

    for (int i = 0; i < tasksArray.size(); ++i) {
        if (!tasksArray[i].isObject()) {
            if (m_logger) {
                m_logger->warning(QString("Skipping invalid task at index %1").arg(i));
            }
            continue;
        }

        QJsonObject taskObj = tasksArray[i].toObject();
        auto tmplResult = parseTemplate(taskObj);

        if (tmplResult.isSuccess()) {
            config.templates.push_back(tmplResult.getValue());
        } else {
            if (m_logger) {
                m_logger->warning(QString("Failed to parse task at index %1: %2")
                    .arg(i)
                    .arg(tmplResult.getErrorMessage()));
            }
        }
    }

    // 验证配置
    std::string error = config.validate();
    if (!error.empty()) {
        return kernel::Result<kernel::task::TaskSystemConfigDTO>::failure(
            kernel::ErrorCode::ValidationError,
            QString::fromStdString(error)
        );
    }

    return kernel::Result<kernel::task::TaskSystemConfigDTO>::success(config);
}

kernel::Result<kernel::task::TaskTemplateConfigDTO> TaskConfigProvider::parseTemplate(
    const QJsonObject& obj)
{
    kernel::task::TaskTemplateConfigDTO tmpl;

    // 解析 name
    if (!obj.contains("name") || !obj["name"].isString()) {
        return kernel::Result<kernel::task::TaskTemplateConfigDTO>::failure(
            kernel::ErrorCode::ParseError,
            "Missing or invalid 'name' field"
        );
    }
    tmpl.name = obj["name"].toString().toStdString();

    // 解析 mutex_task（可选）
    if (obj.contains("mutex_task") && obj["mutex_task"].isString()) {
        tmpl.mutexTask = obj["mutex_task"].toString().toStdString();
    }

    // 解析 caller_num（可选）
    if (obj.contains("caller_num") && obj["caller_num"].isDouble()) {
        tmpl.callerNum = obj["caller_num"].toInt();
    }

    // 解析 allowed_agv_types（可选）
    if (obj.contains("allowed_agv_types") && obj["allowed_agv_types"].isArray()) {
        QJsonArray allowedTypesArray = obj["allowed_agv_types"].toArray();
        for (int i = 0; i < allowedTypesArray.size(); ++i) {
            if (!allowedTypesArray[i].isString()) {
                if (m_logger) {
                    m_logger->warning(QString("Invalid agv type at index %1 in task '%2'")
                        .arg(i).arg(tmpl.name.c_str()));
                }
                continue;
            }

            QString typeStr = allowedTypesArray[i].toString();
            auto agvType = kernel::agv::agvTypeFromString(typeStr.toStdString());
            if (!agvType.has_value()) {
                QString errorMessage = QString("Invalid agv type '%1' in task '%2'")
                    .arg(typeStr)
                    .arg(QString::fromStdString(tmpl.name));
                return kernel::Result<kernel::task::TaskTemplateConfigDTO>::failure(
                    kernel::ErrorCode::InvalidConfiguration,
                    errorMessage
                );
            }
            tmpl.allowedAgvTypes.push_back(agvType.value());
        }
    }

    // 解析 taskchain 数组
    if (!obj.contains("taskchain") || !obj["taskchain"].isArray()) {
        return kernel::Result<kernel::task::TaskTemplateConfigDTO>::failure(
            kernel::ErrorCode::ParseError,
            "Missing or invalid 'taskchain' array"
        );
    }

    QJsonArray taskchainArray = obj["taskchain"].toArray();

    for (int i = 0; i < taskchainArray.size(); ++i) {
        if (!taskchainArray[i].isObject()) {
            if (m_logger) {
                m_logger->warning(QString("Skipping invalid subtask at index %1").arg(i));
            }
            continue;
        }

        QJsonObject subTaskObj = taskchainArray[i].toObject();
        auto subTaskResult = parseSubTask(subTaskObj);

        if (subTaskResult.isSuccess()) {
            tmpl.subTasks.push_back(subTaskResult.getValue());
        } else {
            if (m_logger) {
                m_logger->warning(QString("Failed to parse subtask at index %1: %2")
                    .arg(i)
                    .arg(subTaskResult.getErrorMessage()));
            }
        }
    }

    return kernel::Result<kernel::task::TaskTemplateConfigDTO>::success(tmpl);
}

kernel::Result<kernel::task::SubTaskConfigDTO> TaskConfigProvider::parseSubTask(
    const QJsonObject& obj)
{
    // 参考 task_manager.cpp:280-308

    kernel::task::SubTaskConfigDTO subTask;

    // 解析类型
    if (!obj.contains("typename") || !obj["typename"].isString()) {
        return kernel::Result<kernel::task::SubTaskConfigDTO>::failure(
            kernel::ErrorCode::ParseError,
            "Missing or invalid 'typename' field"
        );
    }

    QString typeStr = obj["typename"].toString();
    subTask.type = stringToSubTaskType(typeStr);

    if (subTask.type == kernel::task::SubTaskType::Unknown) {
        return kernel::Result<kernel::task::SubTaskConfigDTO>::failure(
            kernel::ErrorCode::ParseError,
            QString("Unknown task type: %1").arg(typeStr)
        );
    }

    // 根据类型解析参数
    switch (subTask.type) {
        case kernel::task::SubTaskType::Move:
            if (obj.contains("station_name")) {
                subTask.stationName = obj["station_name"].toString().toStdString();
            }
            if (obj.contains("floor")) {
                subTask.floor = obj["floor"].toInt();
            }
            if (obj.contains("operation")) {
                subTask.operation = obj["operation"].toString().toStdString();
            }
            break;

        case kernel::task::SubTaskType::Jack:
            if (obj.contains("operation_station")) {
                subTask.operationStation = obj["operation_station"].toString().toStdString();
            }
            if (obj.contains("is_up")) {
                subTask.isUp = obj["is_up"].toBool();
            }
            if (obj.contains("wait_time_seconds")) {
                subTask.waitTimeSeconds = obj["wait_time_seconds"].toInt();
            }
            break;

        case kernel::task::SubTaskType::Lift:
            if (obj.contains("lift_num")) {
                subTask.liftNum = obj["lift_num"].toInt();
            }
            if (obj.contains("call_floor")) {
                subTask.callFloor = obj["call_floor"].toInt();
            }
            if (obj.contains("aim_floor")) {
                subTask.aimFloor = obj["aim_floor"].toInt();
            }
            break;

        case kernel::task::SubTaskType::Charge:
            if (obj.contains("charge_point")) {
                subTask.chargePoint = obj["charge_point"].toString().toStdString();
            }
            if (obj.contains("target_battery_level")) {
                subTask.targetBatteryLevel = obj["target_battery_level"].toInt();
            }
            break;

        case kernel::task::SubTaskType::Park:
            if (obj.contains("parking_station")) {
                subTask.parkingStation = obj["parking_station"].toString().toStdString();
            }
            break;

        default:
            break;
    }

    return kernel::Result<kernel::task::SubTaskConfigDTO>::success(subTask);
}

kernel::task::SubTaskType TaskConfigProvider::stringToSubTaskType(const QString& str) const
{
    if (str == "Move") return kernel::task::SubTaskType::Move;
    if (str == "Jack") return kernel::task::SubTaskType::Jack;
    if (str == "Lift") return kernel::task::SubTaskType::Lift;
    if (str == "Charge") return kernel::task::SubTaskType::Charge;
    if (str == "Park") return kernel::task::SubTaskType::Park;
    return kernel::task::SubTaskType::Unknown;
}

// ==================== JSON序列化 ====================

QJsonObject TaskConfigProvider::configToJson(
    const kernel::task::TaskSystemConfigDTO& config) const
{
    QJsonObject rootObj;
    QJsonArray tasksArray;

    for (const auto& tmpl : config.templates) {
        tasksArray.append(templateToJson(tmpl));
    }

    rootObj["tasks"] = tasksArray;
    return rootObj;
}

QJsonObject TaskConfigProvider::templateToJson(
    const kernel::task::TaskTemplateConfigDTO& tmpl) const
{
    QJsonObject obj;
    obj["name"] = QString::fromStdString(tmpl.name);

    if (!tmpl.mutexTask.empty()) {
        obj["mutex_task"] = QString::fromStdString(tmpl.mutexTask);
    }

    if (tmpl.callerNum > 0) {
        obj["caller_num"] = tmpl.callerNum;
    }

    // 序列化 allowed_agv_types
    if (!tmpl.allowedAgvTypes.empty()) {
        QJsonArray allowedTypesArray;
        for (const auto& agvType : tmpl.allowedAgvTypes) {
            allowedTypesArray.append(QString::fromStdString(
                kernel::agv::agvTypeToString(agvType)));
        }
        obj["allowed_agv_types"] = allowedTypesArray;
    }

    QJsonArray taskchainArray;
    for (const auto& subTask : tmpl.subTasks) {
        taskchainArray.append(subTaskToJson(subTask));
    }
    obj["taskchain"] = taskchainArray;

    return obj;
}

QJsonObject TaskConfigProvider::subTaskToJson(
    const kernel::task::SubTaskConfigDTO& subTask) const
{
    QJsonObject obj;
    obj["typename"] = subTaskTypeToString(subTask.type);

    switch (subTask.type) {
        case kernel::task::SubTaskType::Move:
            obj["station_name"] = QString::fromStdString(subTask.stationName);
            obj["floor"] = subTask.floor;
            if (!subTask.operation.empty()) {
                obj["operation"] = QString::fromStdString(subTask.operation);
            }
            break;

        case kernel::task::SubTaskType::Jack:
            if (!subTask.operationStation.empty()) {
                obj["operation_station"] = QString::fromStdString(subTask.operationStation);
            }
            obj["is_up"] = subTask.isUp;
            obj["wait_time_seconds"] = subTask.waitTimeSeconds;
            break;

        case kernel::task::SubTaskType::Lift:
            obj["lift_num"] = subTask.liftNum;
            obj["call_floor"] = subTask.callFloor;
            obj["aim_floor"] = subTask.aimFloor;
            break;

        case kernel::task::SubTaskType::Charge:
            if (!subTask.chargePoint.empty()) {
                obj["charge_point"] = QString::fromStdString(subTask.chargePoint);
            }
            obj["target_battery_level"] = subTask.targetBatteryLevel;
            break;

        case kernel::task::SubTaskType::Park:
            if (!subTask.parkingStation.empty()) {
                obj["parking_station"] = QString::fromStdString(subTask.parkingStation);
            }
            break;

        default:
            break;
    }

    return obj;
}

QString TaskConfigProvider::subTaskTypeToString(kernel::task::SubTaskType type) const
{
    switch (type) {
        case kernel::task::SubTaskType::Move: return "Move";
        case kernel::task::SubTaskType::Jack: return "Jack";
        case kernel::task::SubTaskType::Lift: return "Lift";
        case kernel::task::SubTaskType::Charge: return "Charge";
        case kernel::task::SubTaskType::Park: return "Park";
        default: return "Unknown";
    }
}

} // namespace configuration
} // namespace infrastructure
